﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

[assembly: CLSCompliant(true)]
namespace DbSetupHelper.Common
{
    /// <summary>
    /// Class used to hold information about an element inside the XML Control script.
    /// </summary>
    public class DBScript
    {
        private string scriptFileName;
        private string baseScriptBody;
        private string modifiedScriptBody;
        private bool testInstall;
        private bool disabled;

        private string databaseName;
        private string databaseUserName;
        private string databaseUserPassword;
        private string defaultDatabaseName;
        private string defaultDatabaseUserName;
        private string defaultDatabaseUserPassword;

        /// <summary>
        /// Occurs when [body updated].
        /// </summary>
        public event EventHandler BodyUpdated;

        /// <summary>
        /// Initializes a new instance of the <see cref="DBScript"/> class.
        /// </summary>
        /// <param name="scriptPath">The script path.</param>
        /// <param name="testInstall">if set to <c>true</c> [test install].</param>
        /// <param name="disabled">if set to <c>true</c> [disabled].</param>
        /// <param name="scriptBody">The script body.</param>
        public DBScript(string scriptFileName, bool testInstall, bool disabled, string scriptBody)
        {
            if (string.IsNullOrEmpty(scriptFileName))
                throw new ArgumentNullException("scriptFileName");
            if (string.IsNullOrEmpty(scriptBody))
                throw new ArgumentNullException("scriptBody");

            this.testInstall = testInstall;
            this.disabled = disabled;
            this.scriptFileName = scriptFileName;
            this.baseScriptBody = scriptBody;

            GenerateReplacementScript();
        }

        public DBScript Clone()
        {
            DBScript retValue = new DBScript(scriptFileName, testInstall, disabled, baseScriptBody);

            retValue.databaseName = databaseName;
            retValue.databaseUserName = databaseUserName;
            retValue.databaseUserPassword = databaseUserPassword;
            retValue.defaultDatabaseName = defaultDatabaseName;
            retValue.defaultDatabaseUserName = defaultDatabaseUserName;
            retValue.defaultDatabaseUserPassword = defaultDatabaseUserPassword;
            retValue.modifiedScriptBody = modifiedScriptBody;

            return retValue;
        }

        #region Properties
        /// <summary>
        /// Gets the script path.
        /// </summary>
        /// <value>The script path.</value>
        public string ScriptFileName
        {
            get { return this.scriptFileName; }
        }

        /// <summary>
        /// Gets the script body.
        /// </summary>
        /// <value>The script body.</value>
        public string ScriptBody
        {
            get { return modifiedScriptBody; }
        }

        /// <summary>
        /// Gets the test install.
        /// </summary>
        /// <value>The test install.</value>
        public bool TestInstall
        {
            get { return this.testInstall; }
        }

        /// <summary>
        /// Gets the disabled.
        /// </summary>
        /// <value>The disabled.</value>
        public bool Disabled
        {
            get { return this.disabled; }
            set
            {
                this.disabled = value;
                GenerateReplacementScript();
            }
        }
        #endregion

        /// <summary>
        /// Gets or sets the name of the database user.
        /// </summary>
        /// <param name="userName">Name of the user.</param>
        /// <value>The name of the database user.</value>
        public void SetDatabaseUserName(string userName)
        {
            this.databaseUserName = userName;

            GenerateReplacementScript();
        }

        /// <summary>
        /// Sets the name of the database.
        /// </summary>
        /// <param name="databaseName">Name of the database.</param>
        /// <value>The name of the database.</value>
        public void SetDatabaseName(string databaseName)
        {
            this.databaseName = databaseName;

            GenerateReplacementScript();
        }

        /// <summary>
        /// Sets the database user password.
        /// </summary>
        /// <param name="userPassword">The user password.</param>
        /// <value>The database user password.</value>
        public void SetDatabaseUserPassword(string userPassword)
        {
            this.databaseUserPassword = userPassword;

            GenerateReplacementScript();
        }

        /// <summary>
        /// Gets or sets the name of the database user.
        /// </summary>
        /// <param name="defaultUserName">Default name of the user.</param>
        /// <value>The name of the database user.</value>
        public void SetDefaultDatabaseUserName(string defaultUserName)
        {
            this.defaultDatabaseUserName = defaultUserName;

            GenerateReplacementScript();
        }

        /// <summary>
        /// Sets the name of the database.
        /// </summary>
        /// <param name="defaultDatabaseName">Default name of the database.</param>
        /// <value>The name of the database.</value>
        public void SetDefaultDatabaseName(string defaultDatabaseName)
        {
            this.defaultDatabaseName = defaultDatabaseName;

            GenerateReplacementScript();
        }

        /// <summary>
        /// Sets the database user password.
        /// </summary>
        /// <param name="defaultUserPassword">The default user password.</param>
        /// <value>The database user password.</value>
        public void SetDefaultDatabaseUserPassword(string defaultUserPassword)
        {
            this.defaultDatabaseUserPassword = defaultUserPassword;

            GenerateReplacementScript();
        }

        //TODO: Wouldn't this be awesome if it were threaded. 
        private void GenerateReplacementScript()
        {
            //Semaphore
            if (!disabled)
            {
                modifiedScriptBody = baseScriptBody;

                if (!string.IsNullOrEmpty(databaseName))
                    modifiedScriptBody = modifiedScriptBody.Replace(ReplaceableScriptItems.DatabaseName, databaseName);
                else if (!string.IsNullOrEmpty(defaultDatabaseName))
                    modifiedScriptBody = modifiedScriptBody.Replace(ReplaceableScriptItems.DatabaseName, defaultDatabaseName);

                if (!string.IsNullOrEmpty(databaseUserPassword))
                    modifiedScriptBody = modifiedScriptBody.Replace(ReplaceableScriptItems.DatabasePassword, databaseUserPassword);
                else if (!string.IsNullOrEmpty(defaultDatabaseUserPassword))
                    modifiedScriptBody = modifiedScriptBody.Replace(ReplaceableScriptItems.DatabasePassword, defaultDatabaseUserPassword);

                if (!string.IsNullOrEmpty(databaseUserName))
                    modifiedScriptBody = modifiedScriptBody.Replace(ReplaceableScriptItems.DatabaseUser, databaseUserName);
                else if (!string.IsNullOrEmpty(defaultDatabaseUserName))
                    modifiedScriptBody = modifiedScriptBody.Replace(ReplaceableScriptItems.DatabaseUser, defaultDatabaseUserName);
            }
            else
            {
                modifiedScriptBody = string.Empty;
            }


            if (BodyUpdated != null)
                BodyUpdated(this, new EventArgs());
        }
    }
}
